let _Vue = null
export default class MyVueRouter {
    // 接收两个参数一个是vue构造函数，另一个是可选参数对象，这里只接收第一个参数
    static install(Vue) {
        // 1.判断是否已经注册过插件
        if (MyVueRouter.install.installed) {
            return
        }
        MyVueRouter.install.installed = true
        // 2. 创建一个全局变量接收vue构造函数
        _Vue = Vue
        // 3.把创建Vue的实例传入的router对象注入到Vue实例，这里的this是MyVueRouter这个类
        // 可以通过混入而拿到vue的实例继而拿到创建Vue的实例传入的router对象
        _Vue.mixin({
            beforeCreate () {
                // 这里的this就是vue实例
                // _Vue.prototype.$router = this.$options.router
                // 判断是vue构造函数时给原型加router，否则每个一组件的vue实例的原型都会给加上router
                // 只有Vue构造函数才有传入router这个参数，所以以这个条件判断
                if (this.$options.router) {
                    _Vue.prototype.$router = this.$options.router
                    // 添加完router对象后需要执行createRouteMap和initComponents方法，为了方便调用统一放到init方法中调用
                    this.$options.router.init()

                }
            }
        })

    }
    constructor(options) {
        // options就是我们使用VueRouter构造函数时传递过来的对象，这个对象中就有我们的路由规则
        this.options = options
        this.routeMap = {}
        // observable创建一个响应式的对象，存储当前路由地址，默认为'/'
        this.data = _Vue.observable({
            current:'/'
        })
    }
    // 为了方便调用统一放到init方法中
    init() {
        this.createRouteMap()
        this.initComponents(_Vue)
        this.initEvent()
    }
    createRouteMap() {
        //遍历所有的路由规则 吧路由规则解析成键值对的形式存储到routeMap中
        this.options.routes.forEach(route => {
            this.routeMap[route.path] = route.component
        })
    }
    // 创建router-link组件
    initComponents(Vue) {
        // h方法会创建一个虚拟dom参数一是选择器，也就是你要创建的元素，参数二是设置这个元素的属性，第三个参数是这个元素的子元素
        Vue.component("router-link",{
            props: {
                to: String
            },
            render(h) {
                return h('a',{
                    attrs: {
                        href: this.to
                    },
                    on: {
                        click: this.clickhander
                    }
                }, [this.$slots.default])
            },
            // template: '<a :href="to"><solt></solt></a>'
            methods:{
                clickhander(e){
                    // 参数一是传给pushState的事件对象参数，参数二是页面标题，参数三是需要跳转路由地址
                    history.pushState({},"",this.to)
                    // current是个响应式的对象，当它发生改变后，会重新加载组件并通过router-view重新渲染到视图上
                    this.$router.data.current=this.to
                    // 阻止a标签默认事件，防止它向服务器发送请求而刷新页面
                    e.preventDefault()
                }
            }
        })
        // 保存this
        const self = this
        // 获取到当前路由下的组件并传给h函数渲染到页面中
        Vue.component('router-view',{
            render(h) {
                const cm = self.routeMap[self.data.current]
                return h(cm)
            }
        })
    }
    initEvent() {
        // popstate事件 当历史数据（当点击浏览器的前进后退按钮时触发）发生变化时触发
        window.addEventListener('popstate',() => {
            // window.location.pathname当前浏览器地址栏的路径部分
            this.data.current = window.location.pathname
        })
    }
}